package com.carrot.gateway.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.carrot.common.core.domain.R;
import com.carrot.gateway.app.IAuthAppService;
import com.carrot.gateway.entity.AccessLog;
import com.carrot.gateway.entity.dto.EncryptDataDto;
import com.carrot.gateway.entity.dto.LoginDto;
import com.carrot.gateway.entity.dto.TokenDto;
import com.carrot.gateway.enums.LoginTypeEnum;
import com.carrot.gateway.property.SecurityOAuth2Properties;
import com.carrot.gateway.util.CryptoUtil;
import com.carrot.gateway.util.IpAddressUtil;
import jakarta.annotation.security.PermitAll;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.bind.annotation.*;

/**
 * 获取token
 * @author liuhongzhen
 */
@RestController
@RequestMapping("/api/auth/{ver}")
@AllArgsConstructor
@CrossOrigin
@Slf4j
public class AuthController {

    private final IAuthAppService iAuthService;

    private final SecurityOAuth2Properties securityOAuth2Properties;

    @GetMapping("/token")
    public R<?> getToken(String code,String appName,String redirectUri){
         return iAuthService.getToken(code,redirectUri,appName);
    }

    @GetMapping("/token/refresh")
    public R<?> getTokenByRefreshToken(String refreshToken,String appName,ServerHttpRequest request){
        AccessLog accessLog=new AccessLog();
        accessLog.buildRequestLog(request);
        log.info(accessLog.toString());
        if(StrUtil.isEmpty(refreshToken)){
            return R.fail();
        }
        String clientIp = IpAddressUtil.getClientIpAddress(request);
        return iAuthService.getTokenByRefreshToken(refreshToken,appName,clientIp);
    }

    @PostMapping("/revocationToken")
    public R<?> revocationToken(ServerHttpRequest request,@RequestBody TokenDto token){
        AccessLog accessLog=new AccessLog();
        accessLog.buildRequestLog(request);
        log.info(accessLog.toString());
        return iAuthService.outLogin(request,token);
    }


    @PostMapping("/login")
    public R<?> login(@RequestBody EncryptDataDto encryptData, ServerHttpRequest request){
        AccessLog accessLog=new AccessLog();
        accessLog.buildRequestLog(request);

        Object data = CryptoUtil.rsaDecrypt(encryptData.getEncryptData(), securityOAuth2Properties.getPrivateKey());
        JSONObject jsonObject = JSONUtil.parseObj(data);
        LoginDto loginDTO = BeanUtil.copyProperties(jsonObject, LoginDto.class);
        //用户名
        if(StrUtil.isBlank(loginDTO.getAccount()) || loginDTO.getLoginType() == null){
           return R.fail();
        }
        //获取登录方式
        final LoginTypeEnum typeEnum = LoginTypeEnum.getByCode(loginDTO.getLoginType());
        if(typeEnum == null){
            return R.fail();
        }
        //不同的登录方式校验参数不同
        if(LoginTypeEnum.PASSWD.equals(typeEnum) && StrUtil.isEmpty(loginDTO.getPassword())){
            return R.fail();
        }else if(LoginTypeEnum.SMS_CAPTCHA.equals(typeEnum) && StrUtil.isEmpty(loginDTO.getSmsCaptcha())){
            return R.fail();
        }
        loginDTO.setClientIp(IpAddressUtil.getClientIpAddress(request));

        R login = iAuthService.login(loginDTO);

        accessLog.setRequestParam(loginDTO.getAccount());
        accessLog.setResponseHttpCode(login.getCode());
        accessLog.setResponseParam(login.getMsg());
        accessLog.buildResponseTime();
        accessLog.setUserId(loginDTO.getAccount());

        return login;
    }


    @GetMapping("/sms-captcha")
    public R<?> getSmsCaptcha(String mobile, String appName, ServerHttpRequest request) {
        AccessLog accessLog = new AccessLog();
        accessLog.buildRequestLog(request);
        log.info(accessLog.toString());
        return iAuthService.getSmsCaptcha(mobile,appName);
    }

    /**
     * 获得公钥
     */
    @PermitAll
    @GetMapping("/publicKey")
    public R<String> getPublicKey(){
        return R.ok(securityOAuth2Properties.getPublicKey());
    }
}
